package com.janetfilter.core.models;

import com.janetfilter.core.enums.RuleType;
import com.janetfilter.core.utils.StringUtils;

public class FilterRule {
    private final RuleType type;
    private final String rule;
    private final boolean inverse; // 规则结果取反
    private final boolean white; // 白名单
    private final String strategy; // 策略名

    private FilterRule(RuleType type, String rule) {
        this(type, rule, false, false);
    }

    private FilterRule(RuleType type, String rule, boolean inverse) {
        this(type, rule, inverse, false);
    }

    private FilterRule(RuleType type, String rule, boolean inverse, boolean white) {
        this(type, rule, inverse, white, null);
    }

    private FilterRule(RuleType type, String rule, boolean inverse, boolean white, String strategy) {
        this.type = type;
        this.rule = rule;
        this.inverse = inverse;
        this.white = white;
        this.strategy = strategy;
    }

    public static FilterRule of(String typeStr, String content) {
        return FilterRule.of(typeStr, content, false);
    }

    public static FilterRule of(String typeStr, String content, boolean inverse) {
        return FilterRule.of(typeStr, content, inverse, false);
    }

    public static FilterRule of(String typeStr, String content, boolean inverse, boolean white) {
        return FilterRule.of(typeStr, content, inverse, white, null);
    }

    public static FilterRule of(String typeStr, String content, boolean inverse, boolean white, String strategy) {
        RuleType type = null;
        try {
            type = RuleType.valueOf(typeStr.toUpperCase());
        } catch (Exception ignored) {
        }
        if (null == type) {
            return null;
        }
        return new FilterRule(type, content, inverse, white, strategy);
    }

    public FilterRule append(String line) {
        String content = rule.substring(0, rule.length() - 1) + line.substring(1);
        return new FilterRule(type, content, inverse, white, strategy);
    }

    public boolean test(String content) {
        return inverse != type.getRuler().test(this.rule, content);
    }

    public boolean hasStrategy() {
        return StringUtils.isNoneBlank(strategy);
    }

    @Override
    public String toString() {
        return "FilterRule{" +
                "type=" + type +
                ", rule='" + rule + '\'' +
                ", inverse=" + inverse +
                ", white=" + white +
                ", strategy='" + strategy + '\'' +
                '}';
    }

    public RuleType getType() {
        return type;
    }

    public String getRule() {
        return rule;
    }

    public boolean isInverse() {
        return inverse;
    }

    public boolean isWhite() {
        return white;
    }

    public String getStrategy() {
        return strategy;
    }
}